/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

package com.huawei.api.bean;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.*;
import java.util.function.Consumer;

/**
 * 线程池
 *
 * @since 2023/10/28
 */
public class ThreadPool {
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPool.class);
    private ExecutorService threadPool;

    public ThreadPool(int poolSize) {
        this(poolSize, "workerThread-%d");
    }

    public ThreadPool(int poolSize, String namingPattern) {
        BasicThreadFactory threadFactory = new BasicThreadFactory.Builder().namingPattern(namingPattern).build();
        threadPool = new ThreadPoolExecutor(poolSize, poolSize, 0,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), threadFactory);
    }

    /**
     * 执行异步任务检查
     *
     * @param callable 异步任务
     * @param <T>      任务执行完成回调
     * @return 回调
     */
    public <T> Future<T> call(Callable<T> callable) {
        return threadPool.submit(callable);
    }

    /**
     * 关闭
     */
    public void shutdown() {
        threadPool.shutdown();
    }

    /**
     * 执行异步任务检查
     *
     * @param callableList 异步任务
     * @param callResult   任务执行完成回调
     * @param <T>          结果对象
     */
    public <T> void call(List<Callable<T>> callableList, Consumer<T> callResult) {
        long start = System.currentTimeMillis();
        int successTaskCount = 0;

        try {
            List<Future<T>> futureList = threadPool.invokeAll(callableList);
            for (Future<T> future : futureList) {
                try {
                    T val = future.get();
                    callResult.accept(val);
                    successTaskCount++;
                } catch (InterruptedException | ExecutionException exception) {
                    LOGGER.error("execute thread exception", exception);
                }
            }
        } catch (InterruptedException interruptedException) {
            LOGGER.error("execute invoke exception", interruptedException);
        } finally {
            threadPool.shutdown();
        }

        long end = System.currentTimeMillis();
        LOGGER.info("execute thread end, normal finished size is {}, cost time {}",
                successTaskCount, ((end - start) * 1.0 / 1000) + "s");
        LOGGER.info("checker thread end.");
    }
}
